﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Avalon.Windows.Controls;
using AvalonDock;
using Csla;
using Itenso.Windows.Input;

using OpenExpressApp.MetaModel;
using OpenExpressApp.Module.Command;
using OpenExpressApp.Module.Library;
using OpenExpressApp.Module.Library.Security;
using OpenExpressApp.Module.WPF.Controls;
using OpenExpressApp.Module.WPF.Templete;
using OpenExpressApp.Types;
using OpenExpressApp.WPF.Command;
using OpenExpressApp.WPF.Controls;
using OpenExpressApp.WPF.Editors;
using Wpf.Controls;

namespace OpenExpressApp.Module.WPF
{
    /// <summary>
    /// 为类型的所有孩子属性生成控件。
    /// </summary>
    internal class ChildUIGenerator
    {
        private IUIFactory _uiFactory;

        private WPFObjectView _parentView;

        private Type _parentType;

        private BusinessObjectInfo _parentEntityInfo;

        private IList<BusinessObjectsPropertyInfo> _childrenProperties;

        public ChildUIGenerator(IUIFactory uiFactory, WPFObjectView parentView)
        {
            Debug.Assert(uiFactory != null, "uiFactory != null");
            Debug.Assert(parentView != null, "parentView != null");

            this._uiFactory = uiFactory;
            this._parentView = parentView;
            this._parentType = parentView.BOType;
        }

        /// <summary>
        /// 找出所有可用的孩子属性。
        /// 
        /// 经过权限判断。
        /// </summary>
        private IList<BusinessObjectsPropertyInfo> ChildrenProperties
        {
            get
            {
                if (this._childrenProperties == null)
                {
                    this.InitEntityInfo();
                }
                return this._childrenProperties;
            }
        }

        /// <summary>
        /// 为某一类型所有的孩子属性生成控件。
        /// 生成的同时，要保证parentView与子view、parentControl与子控件之间的关系。
        /// </summary>
        /// <param name="parentType">为这个类型的孩子属性生成</param>
        /// <param name="parentView">生成这个视图的子控件</param>
        /// <param name="parentControl">已经生成好的父控件</param>
        /// <returns>
        /// 返回一个包含所有属性的控件。
        /// 如果没有孩子属性，则返回null。
        /// 如果所有的孩子属性都是直接在父控件中直接显示，而不需要为自己创建新的控件，则返回null。
        /// </returns>
        public FrameworkElement GenerateControl(FrameworkElement parentControl)
        {
            if (parentControl == null) throw new ArgumentNullException("parentControl");

            //如果没有孩子，返回null
            if (this.ChildrenProperties.Count <= 0) return null;

            if (TryGenerateAsTreeChild()) return null;

            SetBounds(parentControl);

            FrameworkElement control = this.CreateTabControl();

            return control;
        }

        /// <summary>
        /// 尝试作为树，直接生成在父控件中。
        /// </summary>
        /// <param name="parentView"></param>
        /// <param name="parentBOInfo"></param>
        /// <param name="childrenPropertiesCount"></param>
        /// <returns></returns>
        private bool TryGenerateAsTreeChild()
        {
            //是否拥有显示在树中的孩子集合
            var hasTreeChild = this._parentEntityInfo.TreeChildPropertyInfo != null;

            //如果只有一个孩子集合，并且这个集合是需要显示在树中的。
            if (hasTreeChild && this.ChildrenProperties.Count == 1)
            {
                //递归在父对象的View对应的Toolbar上生成按钮
                BusinessObjectInfo treeChildBoInfo = this._parentEntityInfo;
                while (treeChildBoInfo.TreeChildPropertyInfo != null)
                {
                    treeChildBoInfo = treeChildBoInfo.TreeChildBoInfo;
                    this._uiFactory.CreateChildToolBar(this._parentView, treeChildBoInfo.BOType);
                }

                return true;
            }
            return false;
        }

        /// <summary>
        /// 生成的所有子控件都放在TabControl里面，然后返回
        /// </summary>
        /// <param name="parentView"></param>
        /// <returns></returns>
        private FrameworkElement CreateTabControl()
        {
            //生成一个TabControl，并监听它的SelectionChanged事件。
            TabControl tab = new TabControl();

            tab.SelectionChanged += (sender, e) =>
            {
                #region 设置每个view的Active状态

                if ((sender == e.OriginalSource) && (e.AddedItems.Count > 0) && (e.AddedItems[0] is TabItem))
                {
                    foreach (TabItem item in e.AddedItems)
                    {
                        var view = item.GetValue(WPFMeta.ObjectViewProperty) as ObjectView;
                        view.IsActive = true;
                    }
                    foreach (TabItem item in e.RemovedItems)
                    {
                        var view = item.GetValue(WPFMeta.ObjectViewProperty) as ObjectView;
                        view.IsActive = false;
                    }
                    e.Handled = true;
                }

                #endregion
            };

            //生成每个子属性
            foreach (BusinessObjectsPropertyInfo childrenProperty in this.ChildrenProperties)
            {
                //创建listViewOfChild
                ListObjectView childrenListView = new ListObjectView(childrenProperty);
                childrenListView.RegionType = this._parentView.RegionType;
                //加入parentView
                this._parentView.AddChildView(childrenListView);

                //每一个孩子属性都生成一个页签
                TabItem tabItem = this.CreateATabItem(childrenProperty, childrenListView);

                if (null != childrenProperty.ChildShowTypeAttribute)
                {
                    tabItem.Visibility = childrenProperty.ChildShowTypeAttribute.Visibility;
                }

                tab.Items.Add(tabItem);
            }

            #region 设置第一个Tab的状态为Active

            if (tab.Items.Count > 0)
            {
                tab.SelectedItem = tab.Items[0];
            }

            #endregion

            #region 只要有一个子显示，则Tab也显示

            Visibility tabVisible = Visibility.Hidden;
            foreach (TabItem item in tab.Items)
            {
                tabVisible = item.Visibility;
                if (tabVisible == Visibility.Visible) break;
            }

            tab.Visibility = tabVisible;

            #endregion

            return tab;
        }

        /// <summary>
        /// 为childrenProperty生成一个页签。
        /// </summary>
        /// <param name="childrenProperty">为这个孩子属性进行生成</param>
        /// <param name="childListView">
        /// childrenProperty所使用的ListObjectView
        /// 孩子属性对应的逻辑视图。
        /// </param>
        /// <returns>
        /// 生成好的页签控件，格式如下：
        /// <![CDATA[
        /// <TabItem>
        ///     <Header>
        ///         <StackPanel Name="Header">
        ///             <TextBlock>Label</TextBlock>
        ///             <Button Name="MaxButton"></Button>
        ///         </StackPanel>
        ///     </Header>
        ///     <Content>
        ///         <DockPanel Name="rootDck">
        ///             <ToolBar Name="childToolBar">一些按钮</ToolBar>
        ///             <ResizingPanel Name="rootResizingPanel">
        ///                 <DockPanel Name="mainContentDck">
        ///                     <ResizingPanel Name="pnlNavigate">
        ///                         <UIElement_AnyType Name="navigateControl"/><!--如果有导航，才有这个元素-->
        ///                         <Grid/><!--显示的主内容-->
        ///                     </ResizingPanel>
        ///                 </DockPanel>
        ///             </ResizingPanel>
        ///         </DockPanel>
        ///     </Content>
        /// </TabItem>
        /// ]]>
        /// </returns>
        private TabItem CreateATabItem(BusinessObjectsPropertyInfo childrenProperty, ListObjectView childListView)
        {
            //生成一个tabItem，并把listViewOfChild附加到上面
            TabItem tabItem = new TabItem();
            tabItem.SetValue(WPFMeta.ObjectViewProperty, childListView);

            #region 创建页签头 StackPanel tabHeader

            StackPanel tabHeader = new StackPanel()
            {
                Orientation = Orientation.Horizontal
            };

            //先写子属性的Label
            tabHeader.Children.Add(new TextBlock()
            {
                Text = childrenProperty.Label
            });

            //再加入最大化按钮
            Button btnMax = new Button();
            btnMax.CommandParameter = childListView;
            ButtonCommand.SetCommand(btnMax, CommandRepository.NewCommand(CommandNames.MaxShowView));
            tabHeader.Children.Add(btnMax);

            #endregion

            tabItem.Header = tabHeader;

            //包含当前属性对应控件以及子属性对应控件
            DockPanel contentDck = new DockPanel();

            #region 创建子ToolBar childToolbar，加入contentDck

            ToolBar childToolbar = null;
            if (childrenProperty.AssociationAttribute.CreateToolbar)
            {
                childToolbar = new ToolBar();
                childToolbar.SetValue(DockPanel.DockProperty, Dock.Top);

                contentDck.Children.Add(childToolbar);
            }

            #endregion

            #region 创建ResizingPanel rootResizingPanel，加入contentDck

            ResizingPanel rootResizingPanel = new ResizingPanel();

            var childType = childrenProperty.BOType;
            var childTypeInfo = ApplicationModel.GetBusinessObjectInfo(childType);
            if (Direction.Horizontal == childTypeInfo.BusinessObjectAttribute.Direction)
            {
                rootResizingPanel.Orientation = Orientation.Horizontal;
            }
            else
            {
                rootResizingPanel.Orientation = Orientation.Vertical;
            }

            contentDck.Children.Add(rootResizingPanel);

            #endregion

            #region 处理主要内容的控件生成

            //使用一个DockPanel来装主要的显示控件
            DockPanel mainContentDck = new DockPanel();
            FrameworkElement toolbarServicedControl = null;

            if (null != childListView.NavigateQueryView)
            {
                #region 如果有导航面板，则在导航面板中增加一个ListViewController，以便导航查询数据

                ResizingPanel pnlNavigate = new ResizingPanel();

                //这一步会生成一个导航控件
                UIElement navigateControl = childListView.NavigateQueryView.Control as UIElement;
                navigateControl.SetValue(ResizingPanel.ResizeWidthProperty, new GridLength(200));
                pnlNavigate.Children.Add(navigateControl);

                //生成Grid并添加到导航面板中
                var controller = new ListViewController(childListView);
                toolbarServicedControl = controller.Control;
                pnlNavigate.Children.Add(toolbarServicedControl);

                mainContentDck.Children.Add(pnlNavigate);

                #endregion
            }
            else
            {
                toolbarServicedControl = childListView.Control as FrameworkElement;

                //添加列表
                mainContentDck.Children.Add(toolbarServicedControl);
            }

            rootResizingPanel.Children.Add(mainContentDck);

            #endregion

            if (childToolbar != null)
            {
                //设置toolBar服务的内容为mainContentDck
                childToolbar.SetServicedControl(toolbarServicedControl);
                childListView.ToolBar = childToolbar;

                this._uiFactory.CreateChildToolBar(childListView, childrenProperty.BOType);
            }

            //递归查找子子对象！
            if (childrenProperty.AssociationAttribute.IsRecur)
            {
                var childGenerator = new ChildUIGenerator(this._uiFactory, childListView);
                UIElement childchild = childGenerator.GenerateControl(mainContentDck);
                if (null != childchild)
                {
                    rootResizingPanel.Children.Add(childchild);
                }
            }

            tabItem.Content = contentDck;

            ViewAdapter.AdaptView(childListView, tabItem);

            return tabItem;
        }

        /// <summary>
        /// 初始化元数据信息
        /// </summary>
        private void InitEntityInfo()
        {
            this._parentEntityInfo = ApplicationModel.GetBusinessObjectInfo(this._parentType);

            //获取有权限的子对象
            var currentIdentity = ApplicationContext.User.Identity as OEAIdentity;
            var operationId = new Guid(CommandNames.CanViewObject);
            var childrenProperties = this._parentEntityInfo.BOsPropertyInfos
                .Where(p =>
                {
                    if (p.AssociationAttribute.IsVisible == false) return false;

                    var entityInfo = ApplicationModel.GetBusinessObjectInfo(p.BOType);
                    return currentIdentity.HavePermissionOnOperation(entityInfo.Id, operationId);
                }).ToList();
            this._childrenProperties = childrenProperties;
        }

        /// <summary>
        /// 设置parentControl的Dock、Width、Height
        /// </summary>
        /// <param name="parentControl"></param>
        /// <param name="parentBOInfo"></param>
        private void SetBounds(FrameworkElement parentControl)
        {
            if (Direction.Horizontal == this._parentEntityInfo.BusinessObjectAttribute.Direction)
            {
                parentControl.SetValue(DockPanel.DockProperty, Dock.Left);
                parentControl.SetValue(ResizingPanel.ResizeWidthProperty, new GridLength(200));
            }
            //多个细表时设定细表高度
            else if (parentControl.GetType() != typeof(AutoGrid))
            {
                parentControl.SetValue(DockPanel.DockProperty, Dock.Top);
                parentControl.SetValue(ResizingPanel.ResizeHeightProperty, new GridLength(100));
            }
        }
    }
}
